/* -----------------
* brief
* 1. this is code gen by tools
 */

package service

import (
	"errors"
	"fmt"
	"github.com/mjiulee/lego"
	"saas_sys_base/common"
	appmanagerModel "saas_sys_base/modules/appmanager/models"

	configService "saas_sys_base/modules/config/service"
	. "saas_sys_base/modules/tenant/models"
	. "saas_sys_base/modules/user/service"
)

const limitParentNum int = 1//父租户层级数目

type TenantService struct {
	// add your model here
	tbTenant              Tenant
	tbAppTenantPermission appmanagerModel.AppTenantPermission

	tenantMemberService   TenantMemberService
	appconfigService    configService.AppConfigService

	userService UserService

}

func (t *TenantService) ListTenant(keyword string, page, psize int, orderField, order string) ([]map[string]string, int64, error) {
	// 业务查询
	queryMap := map[string]interface{}{
		"table":  map[string]string{"table": "tb_tenant", "alias": "t1"},
		"fields": []string{"t1.*"},
		"join":   []map[string]string{
			// map[string]string{"table": "tb_xx as t2", "on": "t2.xid = t1.id"},
		},
		"where": []lego.QMapWhereField{
			//{"t1.if_del", "=", 0, "AND", false},
		},
		"search": map[string]string{
			//"t1.id": req.Keyword,
			"t1.name": keyword,
		},
		"orders": []string{"t1.id asc"},
		"page": map[string]int{
			"page":  page,
			"psize": psize,
		},
	}

	if orderField != "" && order != "" {
		orderStr := fmt.Sprintf("t1.%s %s", orderField, order)
		queryMap["orders"] = []string{orderStr, "t1.cdate asc"}
	}

	return lego.QueryListByMap(queryMap)
}

/* 根据id获取记录
 * -----------------
 */
func (t *TenantService) GetTenantById(id int64) *Tenant {
	return t.tbTenant.RecodeById(id)
}

/* 添加
 * -----------------
 */
func (t *TenantService) SaveTenant(item2add *Tenant) bool {
	return t.tbTenant.AddRecode(item2add)
}

/* 删除(硬删除)*/
func (t *TenantService) DelTenantById(id int64) bool {
	return t.tbTenant.DelRecodeById(id)
}

/* 更新
 * -----------------*/
func (t *TenantService) UpdateTenant(rc *Tenant) bool {
	return t.tbTenant.UpdateRecode(rc)
}

//自定义函数

//创建商户，并且自动加入一个初始成员,初始成员角色为boss
// TODO 应该返回租户profile
func (t *TenantService) CreateTenantWithMember(who *common.Who, name string) (*Tenant, *TenantMember, error) {
	config, err := t.appconfigService.GetConfigByWho(*who)
	if err != nil {
		return nil, nil, err
	}

	if !config.App_Config_Data.Attr.Is_TenantApp {
		return nil, nil, errors.New("create tenant only support in tenant app")
	}

	miniAppId := who.MiniAppId
	memberUid := who.Uid

	newTenant := new(Tenant)
	newTenant.Name = name
	//var rberr error
	session := lego.GetDBEngine().NewSession()
	defer session.Close()
	err = session.Begin()

	isSuccess := t.tbTenant.AddRecodeWithsession(session, newTenant)
	if !isSuccess {
		_ = session.Rollback()
		return nil, nil, errors.New("CreateTenantWithMember failed")
	}

	newMember := new(TenantMember)
	newMember.TenantId = newTenant.Id
	newMember.Uid = memberUid
	newMember.State = common.STATE_YES
	newMember.Role = TENANT_ROLE_SUPER_ADMIN
	isSuccess = t.tenantMemberService.tbTenantMember.AddRecodeWithsession(session, newMember)
	if !isSuccess {
		_ = session.Rollback()
		return nil, nil, errors.New("CreateTenantWithMember failed")
	}
	newAppPermission := new(appmanagerModel.AppTenantPermission)
	newAppPermission.CheckMode = common.APP_PERMISSION_CHECK_MODE_ALWAYS_VALID
	newAppPermission.MiniAppId = miniAppId
	newAppPermission.TenantId = newTenant.Id
	isSuccess = t.tbAppTenantPermission.AddRecodeWithsession(session, newAppPermission)
	if !isSuccess {
		_ = session.Rollback()
		return nil, nil, errors.New("CreateTenantWithMember failed")
	}

	err = session.Commit()
	return newTenant, newMember, err
}

//创建商户（没有自动加成员）
func (t *TenantService) CreateTenant() (*Tenant, error) {
	item2add := new(Tenant)
	isErr := t.tbTenant.AddRecode(item2add)
	if isErr {
		return nil, errors.New("CreateTenant failed")
	}

	return item2add, nil
}

//创建子租户，返回子租户数据
func (t *TenantService) CreateSubTenant(tenantWho *common.Who, mainTenantId int64) (subTenant *Tenant, err error) {
	config, err := t.appconfigService.GetConfigByWho(*tenantWho)
	if err != nil {
		return nil, err
	}

	if !config.App_Config_Data.Attr.Is_TenantApp {
		return nil, errors.New("create tenant only support in tenant app")
	}

	miniAppId := tenantWho.MiniAppId
	//memberUid := tenantWho.Uid

	parentTenant := t.tbTenant.RecodeById(mainTenantId)
	if parentTenant == nil {
		return nil, errors.New("parent tenant not exist")
	}

	newTenant := new(Tenant)
	newTenant.ParentTenantId = parentTenant.Id
	newTenant.Depth = parentTenant.Depth + 1             // common.TENANT_DEPTH_1 //深度1表示二级租户
	newTenant.TenantType = common.TENANT_TYPE_SINGE_SHOP //二级租户一般为单店租户模式
	//var rberr error
	s := lego.NewDBSession()
	defer s.Close()
	err = s.Begin()

	isSuccess := t.tbTenant.AddRecodeWithsession(s.GetSession(), newTenant)
	if !isSuccess {
		_ = s.Rollback()
		return nil, errors.New("CreateTenantWithMember failed")
	}

	/*newMember := new(TenantMember)
	newMember.TenantId = newTenant.Id
	newMember.Uid = memberUid
	newMember.State = common.STATE_YES
	isSuccess = t.tenantMemberService.tbTenantMember.AddRecodeWithsession(session, newMember)
	if !isSuccess {
		_ = session.Rollback()
		return nil, errors.New("CreateTenantWithMember failed")
	}*/
	newAppPermission := new(appmanagerModel.AppTenantPermission)
	newAppPermission.CheckMode = common.APP_PERMISSION_CHECK_MODE_ALWAYS_VALID
	newAppPermission.MiniAppId = miniAppId
	newAppPermission.TenantId = newTenant.Id

	isSuccess = t.tbAppTenantPermission.AddRecodeWithsession(s.GetSession(), newAppPermission)
	if !isSuccess {
		_ = s.Rollback()
		return nil, errors.New("CreateTenantWithMember failed")
	}

	err = s.Commit()

	return newTenant, nil
}

/*
	item2add := new(Tenant)

	rcTenant := t.tbTenant.RecodeById(tenantWho.TenantId)
	if rcTenant == nil {
		return nil, errors.New("parent tenant not exist")
	}

	item2add.ParentTenantId = rcTenant.Id
	item2add.Depth = common.TENANT_DEPTH_1 //深度1表示二级租户
	isErr := t.tbTenant.AddRecode(item2add)
	if isErr {
		return nil, errors.New("CreateTenant failed")
	}
*/
//在指定uid的用户是否是租户的成员，是否具有此租户的权限
func (t *TenantService) HasPermissionInTenant(appwho *common.Who, tid int64, uid int64) bool {
	if tid == 0 { //tid为0表示平台租户，默认任意用户都有平台租户的权限
		return true
	}

	config, err := t.appconfigService.GetConfigByWho(*appwho)
	if err != nil {
		return false
	}

	isTenantApp := config.App_Config_Data.Attr.Is_TenantApp
	if isTenantApp == false {
		return true
	}

	tenant := t.GetTenantById(tid)
	if tenant == nil {
		return false
	}

	hasPermission := t.tenantMemberService.HasPermissionInTenant(tid, uid)
	if hasPermission == false {
		//再查一下这个uid是否再父租户中
		rcTenant := t.tbTenant.RecodeById(tid)
		if rcTenant == nil {
			return false
		}
		parentTid := rcTenant.ParentTenantId
		countParent := 0
		for parentTid > 0 && countParent <= limitParentNum { //加个防御，防止因为数据库parentid配错，导致死循环
			hasPermission = t.tenantMemberService.HasPermissionInTenant(parentTid, uid)
			if hasPermission == true {
				return true //有权限则返回true
			}
			rcParentTenant := t.tbTenant.RecodeById(parentTid)
			parentTid = rcParentTenant.ParentTenantId
			countParent = countParent + 1
		}
		return false
	} else {
		return true
	}
}

func (t *TenantService) GetTenantMemberByUidTidAndRole(userWho *common.Who) *TenantMember {
	rc := t.tenantMemberService.GetTenantMemberByUidAndRole(userWho.Uid, TENANT_ROLE_SUPER_ADMIN)
	return rc
}

func (t *TenantService) SwitchCurrentTenant(userWho *common.Who, tid int64) (*Tenant, error) {
	tenant := t.GetTenantById(tid)
	if tenant == nil {
		return nil, fmt.Errorf("Not found uid<%d>", tid)
	}

	/*_, total, err := t.tenantMemberService.ListTenantByMemberUid(userWho.Uid)
	if err != nil {
		return nil, err
	}*/
	//检查租户状态：如果用户名下只有1个租户，可以切换当前租户，如果已经有租户了，只能切换提交审核资料的且缴纳了费用的
	//if (total > 1) && (tenant.IsPayed == common.STATE_NO || tenant.RegisterState == common.REG_STATE_CHECK_PASS) {  /* tenant.RegisterState == common.REG_STATE_SUBMITED*/
	//	return nil, fmt.Errorf("can not switch tenant, due to IsPayed<%d> RegisterState<%d>", tenant.IsPayed, tenant.RegisterState)
	//}

	//检查权限
	hasPermission := t.HasPermissionInTenant(userWho, tid, userWho.Uid)
	if !hasPermission {
		return nil, fmt.Errorf("can not switch tenant, due to Uid<%d> no permission for tenant<%d>!", userWho.Uid, tid)
	}

	err := t.userService.SwitchCurrentTenant(userWho, tid)
	if err != nil {
		return nil, err
	}

	return tenant, nil
}

func (t *TenantService) GetCurrentTenant(userWho *common.Who) (*Tenant, error) {
	user := t.userService.GetUserById(userWho.Uid)
	if user == nil {
		return nil, fmt.Errorf("not found uid<%d>", userWho.Uid)
	}

	tenant := t.tbTenant.RecodeById(user.CurrentTid)
	return tenant, nil
}

func (t *TenantService) UpdateIsPayedState(userWho *common.Who, state int) (*Tenant, error) {
	if state != common.STATE_YES && state != common.STATE_NO {
		return nil, fmt.Errorf("para err state<%d>", state)
	}

	tenant := t.GetTenantById(userWho.TenantId)
	if tenant == nil {
		return nil, fmt.Errorf("Not found uid<%d>", userWho.TenantId)
	}

	tenant.IsPayed = state

	t.tbTenant.UpdateRecodeFields(tenant, Field_IsPay)

	return tenant, nil
}

func (t *TenantService) UpdateRegisterState(tid int64, state int) (*Tenant, error) {
	if state != common.REG_STATE_NONE && state != common.REG_STATE_SUBMITED && state != common.REG_STATE_CHECK_PASS {
		return nil, fmt.Errorf("para err state<%d>", state)
	}

	tenant := t.GetTenantById(tid)
	if tenant == nil {
		return nil, fmt.Errorf("Not found uid<%d>", tid)
	}

	tenant.RegisterState = state
	t.tbTenant.UpdateRecodeFields(tenant, Field_RegisterState)

	return tenant, nil
}



